<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>
        // var names = ["abc_0", "bca_1", "cab_2", "aaa_3"]
        // // callback回调、index从第几个开始迭代
        // function selfFach(callback, index = 0) {
        //     if (!this[index]) {
        //         console.error(`${this} ${index} is not default`)
        //         return
        //     }
        //     while (index < this.length) {
        //         callback(this[index], index, this)
        //         index += 1
        //     }
        // }
        // Array.prototype.selfFach = selfFach

        // names.selfFach((item, index, names) => {
        //     console.log(item, index, names);
        // }, 2)

        // function App() {
        //     const mountedRef = useRefs()
        //     useEffect(
        //         () => {
        //             if (!mountedRef.current) {
        //                 // undefind 表示是第一次进来
        //                 // componentDidMount()
        //                 mountedRef.current = true
        //             } else {
        //                 // 再次更新就是第二次进来了
        //                 // componentDidUpdate
        //             }
        //         }
        //     );
        // }

        // 手动实现一个promise
        // promise 实现原理
        // 1. promise  接受一个回调任务，在new promise(executor)的时候会立即执行回调
        // 2. executor 内部的异步任务被放入到宏/微任务队列等待执行
        // 3. then/catche 手机相应成功或者失败的回调
        // 4. executor 异步任务得到结果后被执行，触发resolve、reject从成功或者失败队列中依次执行

        // Promise/A+规范的三种状态
        const PENDING = 'pending'     // （等待态）
        const FULFILLED = 'fulfilled' // （执行态）
        const REJECTED = 'rejected'   // （拒绝态）
        // 以上状态不可逆
        class Npromise {
            constructor(executor) {
                // 异步成功的时候的队列
                this._resolveQueue = []
                // 异步失败的时候的队列
                this._rejectQueue = []
                // 当前promise的状态 默认空闲
                this._status = PENDING

                // executor 接受两个参数 resolve 和 reject 分别是抛出成功、失败的回调信息
                let _resolve = (val) => {
                    // 成功的回调
                    if (this._status !== PENDING) return
                    this._status = FULFILLED

                    while (this._resolveQueue.length) {
                        // 移除第一位并返回
                        const callback = this._resolveQueue.shift()
                        callback(val)
                    }
                }

                // 实现同resolve
                let _reject = (val) => {
                    // 成功的回调
                    if (this._status !== PENDING) return
                    this._status = REJECTED

                    while (this._rejectQueue.length) {
                        const callback = this._rejectQueue.shift()
                        callback(val)
                    }
                }

                // new Promise 的时候立马执行回调
                executor(_resolve, _reject)
            }

            // then方法,接收一个成功的回调和一个失败的回调，并push进对应队列
            then(resolveFn) {
                //  resolveFn = (结果)=> {}
                // then 需要支持链式调用，也就是可以一直 .then().then().then().then().then()
                // 如果需要这样处理 也就是说 then需要返回一个 promise
                return new Npromise((resolve, reject) => {
                    // 这也就是说 为什么调用者必须使用 resolve() 或者 reject() 以后 then才有用
                    // 因为 then 只是加入了一个队列，resolve 才是执行
                    const fulfilledFn = value => {
                        console.log('value value ====> ', value)
                        try {
                            // 执行第一个（当前的）promise的成功回调，并获取返回值
                            let result = resolveFn(value)
                            // 判断结果 如果结果是promise, 那么等待promise状态变更，否则直接resolve
                            if (result instanceof Npromise) {
                                result.then(resolve, reject)
                            } else {
                                resolve(result)
                            }
                        } catch (error) {
                            reject(error)
                        }
                    }

                    this._resolveQueue.push(fulfilledFn)
                })
            }

            catch(rejectFn) {
                this._rejectQueue.push(rejectFn)
            }
        }

        const Por = new Npromise((resolve, reject) => {
            setTimeout(() => {
                resolve('result')
            }, 1000)
        })

        Por.then(res => {
            console.log('res ========>1 ', res)
            return 1
        }).then(res => {
            console.log('res ========>2 ', res)
            return 2
        }).then(res => {
            console.log('res ========>3 ', res)
            return 3
        }).then(res => {
            console.log('res ========>4 ', res)
            return 4
        })

    </script>
</body>

</html>